# -*- coding: utf-8 -*-
#!/usr/bin/env python

import socket
import argparse
import urlparse
import sys
import os
import time
import random

def host_resolve(url, outpath):
    if not os.path.isdir(outpath):
        os.makedirs(outpath)
    result = urlparse.urlparse(url)
    netloc = result.netloc
    port = result.port
    if port is None:
        if "http" == result.scheme:
            port = 80
        elif "https" == result.scheme:
            port = 443
        else:
            print "unknow shecme: %s" % result.scheme
            return 1
    outfile = os.path.join(outpath, netloc)
    while True:
        host = socket.gethostbyname(netloc)
        resolved = False
        if os.path.isfile(outfile):
            with open(outfile, 'rb') as f:
                if "%s:%s" % (host, port) in f.read().split('\n'):
                    print "host %s already resolved" % host
                    resolved = True
        if not resolved:
            with open(os.path.join(outpath, netloc), 'a+') as f:
                f.write("%s:%s" % (host, port))
                f.write('\n')
        time.sleep(random.randint(0,60))
    return 0

def try_connect(host, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    r = sock.connect_ex((host, int(port)))
    sock.close()
    return r

def host_stat(infile, outfile):
    if not os.path.isfile(infile):
        print "infil %s does not exists" % infile
    outpath = os.path.dirname(outfile)
    if not os.path.isdir(outpath):
        os.makedirs(outpath)
    hosts = []
    with open(infile, 'rb') as f:
        hosts = f.read().split('\n')
    hosts = [x.strip() for x in hosts]
    while True:
        for host in hosts:
            h = host.split(':')
            if len(h) < 2:
                print "invalid host pattern %s" % host
                continue
            print "try connect %s:%s" % (h[0], h[1])
            error = try_connect(h[0], h[1])
            o = '%s,%s,%s' % (time.time(), host, error)
            with open(outfile, 'a+') as f:
                f.write(o)
                f.write('\n')
            time.sleep(1)
        print "waiting for next loop"
        time.sleep(random.randint(0, 60))
    return 0

def main():
    if len(sys.argv) < 2:
        usage()
        return 1
    command = sys.argv[1]
    if "resolve" == command:
        parser = resolve_cli_parser()
        know_args = parser.parse_args(sys.argv[2:])
        if know_args.host is None or know_args.outpath is None:
            parser.print_usage()
            return 1
        return host_resolve(know_args.host, know_args.outpath)
    elif "stat" == command:
        parser = stata_cli_parser()
        know_args = parser.parse_args(sys.argv[2:])
        if know_args.infile is None or know_args.outfile is None:
            parser.print_usage()
            return 2
        return host_stat(know_args.infile, know_args.outfile)
    else:
        usage()
        return 3
    
def stata_cli_parser():
    parser = argparse.ArgumentParser(prog='host stat', description='Host stat')
    parser.add_argument('-i', '--infile', dest='infile', help="host ip addresses input file")
    parser.add_argument('-o', '--outfile', dest='outfile', help="host ip stat out file")
    return parser

def resolve_cli_parser():
    parser = argparse.ArgumentParser(prog='host resolve', description='host resolve to ip addresses')
    parser.add_argument('-n', '--hostname', dest='host', help="host name or url")
    parser.add_argument(
        '-o', '--outpath', dest='outpath', help="out path of resolve result")
    return parser

def usage():
    print "%s <resolve|stat> <options>" % sys.argv[0]

if __name__ == '__main__':
    main()
